package com.wolfalpha.lwtool.net;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;

import com.wolfalpha.lwtool.exception.InternetErrorException;

import android.util.Log;

public class Client {

	private HttpClient httpClient;

	private static final int SAFE_IDMP_RETRY = 5;
	private static final int SAFE_UNIDMP_RETRY = 3;

	public Client() {
		HttpParams params = new BasicHttpParams();
		SchemeRegistry schemeRegistry = new SchemeRegistry();
		schemeRegistry.register(new Scheme("http", PlainSocketFactory
				.getSocketFactory(), 80));
		ClientConnectionManager cm = new ThreadSafeClientConnManager(params,
				schemeRegistry);
		// params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 60000);
		// params.setParameter(CoreConnectionPNames.SO_TIMEOUT, 60000);
		httpClient = new DefaultHttpClient(cm, params);
	}

	public HttpClient getHttpClient() {
		return httpClient;
	}

	/**
	 * 非幂等请求，使用HTTP_POST发送，不重试
	 * 
	 * @param url
	 * @param pairs
	 * @return
	 * @throws Exception
	 */
	public HttpResponse nonIdmpRequest(String url, NameValuePair... pairs)
			throws Exception {

		HttpResponse response = http_post(url, pairs);
		return response;

	}

	/**
	 * 安全幂等请求，使用HTTP_GET发送，自动重试5次
	 * 
	 * @param url
	 * @param pairs
	 * @return
	 * @throws Exception
	 */
	public HttpResponse safeIdmpRequest(String url, NameValuePair... pairs)
			throws Exception {

		HttpResponse response = null;
		int retry = 0;
		while (response == null) {
			try {
				response = http_get(url, pairs);
			} catch (Exception e) {
				retry++;
				System.err.println("network error, retry..."
						+ String.valueOf(retry));
				if (retry >= SAFE_IDMP_RETRY) {
					throw e;
				}
			}
		}

		return response;
	}

	/**
	 * 不安全幂等请求，使用HTTP_POST发送，自动重试3次
	 * 
	 * @param url
	 * @param pairs
	 * @return
	 * @throws Exception
	 */
	public HttpResponse unSafeIdmpRequest(String url, NameValuePair... pairs)
			throws Exception {

		HttpResponse response = null;
		int retry = 0;
		while (response == null) {
			try {
				response = http_post(url, pairs);
			} catch (Exception e) {
				e.printStackTrace();
				retry++;
				System.err.println("network error, retry..."
						+ String.valueOf(retry));
				if (retry >= SAFE_UNIDMP_RETRY) {
					throw e;
				}
			}
		}
		return response;
	}

	private synchronized HttpResponse http_get(String url,
			NameValuePair... pairs) throws Exception {

		StringBuilder params = new StringBuilder();
		if (pairs.length != 0) {
			params.append("?");
			for (int i = 0; i < pairs.length; i++) {
				if (i != 0) {
					params.append('&');
				}
				params.append(pairs[i].getName()).append('=')
						.append(pairs[i].getValue());
			}
		}
		Log.d("network", "----------get begin-----------");
		Log.d("network", url + params.toString());

		HttpGet request = new HttpGet(url
				+ params.toString().replace(" ", "%20"));
		HttpResponse response = this.getHttpClient().execute(request);
		Log.d("network", "----------get end-----------");
		return response;
	}

	private synchronized HttpResponse http_post(String url,
			NameValuePair... pairs) throws Exception {
		HttpPost request = new HttpPost(url);
		Log.d("network", "----------post begin-----------");
		Log.d("network", url);
		List<NameValuePair> argList = new ArrayList<NameValuePair>();
		for (NameValuePair pair : pairs) {
			argList.add(pair);
			Log.d("network", pair.getName() + ": " + pair.getValue());
		}
		request.setHeader("Content-Type",
				"application/x-www-form-urlencoded; charset=utf-8");
		Log.d("network", "----------post end2-----------");
		request.setEntity(new UrlEncodedFormEntity(argList, "UTF-8"));
		Log.d("network", "----------post end1-----------");
		HttpResponse response = this.getHttpClient().execute(request);
		Log.d("network", "----------post end-----------");
		return response;
	}

	/**
	 * @throws InternetErrorException
	 * @Function : 发送Post请求到服务器
	 * @Param : params请求体内容，encode编码格式
	 */
	public String submitPostData(String strUrlPath, Map<String, String> params,
			String encode) throws InternetErrorException {

		byte[] data = getRequestData(params, encode).toString().getBytes();// 获得请求体
		try {
			URL url = new URL(strUrlPath);
			HttpURLConnection httpURLConnection = (HttpURLConnection) url
					.openConnection();
			httpURLConnection.setConnectTimeout(3000); // 设置连接超时时间
			httpURLConnection.setDoInput(true); // 打开输入流，以便从服务器获取数据
			httpURLConnection.setDoOutput(true); // 打开输出流，以便向服务器提交数据
			httpURLConnection.setRequestMethod("POST"); // 设置以Post方式提交数据
			httpURLConnection.setUseCaches(false); // 使用Post方式不能使用缓存
			// 设置请求体的类型是文本类型
			httpURLConnection.setRequestProperty("Content-Type",
					"application/x-www-form-urlencoded");
			// 设置请求体的长度
			httpURLConnection.setRequestProperty("Content-Length",
					String.valueOf(data.length));
			// 获得输出流，向服务器写入数据
			OutputStream outputStream = httpURLConnection.getOutputStream();
			outputStream.write(data);

			int response = httpURLConnection.getResponseCode(); // 获得服务器的响应码
			if (response == HttpURLConnection.HTTP_OK) {
				InputStream inptStream = httpURLConnection.getInputStream();
				return dealResponseResult(inptStream); // 处理服务器的响应结果
			}
			httpURLConnection.disconnect();
			outputStream.close();
		} catch (IOException e) {
			e.printStackTrace();
			return "err: " + e.getMessage().toString();
		} catch (Exception e) {
			throw new InternetErrorException("submit");
		}
		return "-1";
	}

	/**
	 * @Function : 封装请求体信息
	 * @Param : params请求体内容，encode编码格式
	 */
	public static StringBuffer getRequestData(Map<String, String> params,
			String encode) {

		StringBuffer stringBuffer = new StringBuffer(); // 存储封装好的请求体信息
		try {
			for (Map.Entry<String, String> entry : params.entrySet()) {
				stringBuffer.append(entry.getKey()).append("=")
						.append(entry.getValue()).append("&");
			}
			stringBuffer.deleteCharAt(stringBuffer.length() - 1); // 删除最后的一个"&"
		} catch (Exception e) {
			e.printStackTrace();
		}
		return stringBuffer;
	}

	/**
	 * @Function : 处理服务器的响应结果（将输入流转化成字符串）
	 * @Param : inputStream服务器的响应输入流
	 */
	public static String dealResponseResult(InputStream inputStream) {
		String resultData = null; // 存储处理结果
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		byte[] data = new byte[1024];
		int len = 0;
		try {
			while ((len = inputStream.read(data)) != -1) {
				byteArrayOutputStream.write(data, 0, len);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		resultData = new String(byteArrayOutputStream.toByteArray());
		return resultData;
	}

}
